
package com.ami.kvm.isocaching;

import com.ami.kvm.jviewer.Debug;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.BufferUnderflowException;
import java.util.LinkedList;

public class ReadAheadCache extends Thread {
	public static final int MAX_CACHE_SIZE = 256;
	public static final int MAX_BANK_SIZE = 64;
	private LinkedList<SectorBank> sectorDataCache = null;

	private RequestHandler requestHandler = null;
	private CacheManager cacheManager = null;
	private ISOReader isoReader = null;
	private RandomAccessFile imageFile = null;
	private boolean running = false;
	private boolean cacheLocked = false;
	private boolean fileReadWait = false;
	private byte[] sectorData = null;
	private final Object cacheSync = new Object();
	private final Object readSync = new Object();
	private final Object cacheLock = new Object();
	private final Object fileLock = new Object();
	private final Object reqSync = new Object();

	private int numSectors;

	private long startingSector;

	public ReadAheadCache(RandomAccessFile paramRandomAccessFile) {
		this.imageFile = paramRandomAccessFile;
		if (getSectorDataCache() == null)
			setSectorDataCache(new LinkedList());
		if (this.requestHandler == null) {
			this.requestHandler = new RequestHandler(this);
			this.requestHandler.startThread();
			this.requestHandler.setName("RequestHandler");
		}
		if (this.cacheManager == null) {
			this.cacheManager = new CacheManager(this);
			this.cacheManager.startThread();
			this.cacheManager.setName("CacheManager");
		}
		this.isoReader = new ISOReader();
	}

	public void run() {
		while (this.running) {
			synchronized (this.cacheSync) {
				try {
					this.sectorData = readSectorData();
					synchronized (this.readSync) {
						this.readSync.notifyAll();
					}
					this.cacheSync.wait();
				} catch (InterruptedException localInterruptedException) {
					Debug.out.println(localInterruptedException);
				}
			}
		}
	}

	public byte[] readSectorData() {
		byte[] arrayOfByte1 = null;
		int i = 2048 * this.numSectors;
		long l1 = getSectorKey(this.startingSector);
		int j = (int) (2048L * (this.startingSector - l1));
		byte[] arrayOfByte2 = null;
		byte[] arrayOfByte3 = null;
		if (l1 >= 0L)
			if (!isCacheLocked()) {
				SectorBank localSectorBank = getSectorBank(l1);
				arrayOfByte1 = new byte[i];
				if (this.startingSector + this.numSectors > l1 + 64L) {
					int k = (int) (this.startingSector + this.numSectors - (l1 + 64L));
					int m = (int) (l1 + 64L - this.startingSector);
					long l2 = this.startingSector + m;
					int n = 2048 * m;
					int i1 = 2048 * k;
					byte[] arrayOfByte5 = localSectorBank.getSectorData();

					arrayOfByte2 = new byte[n];
					arrayOfByte3 = new byte[i1];
					if (arrayOfByte5 != null)
						if (arrayOfByte5.length >= j + arrayOfByte2.length) {
							System.arraycopy(arrayOfByte5, j, arrayOfByte2, 0, arrayOfByte2.length);
							rearrangeSectorBank(localSectorBank);
						} else {
							arrayOfByte2 = null;
						}
					l1 = getSectorKey(l2);
					if (l1 >= 0L) {
						j = (int) (2048L * (l2 - l1));
						try {
							localSectorBank = getSectorBank(l1);
							byte[] arrayOfByte6 = getSectorBank(l1).getSectorData();
							if (arrayOfByte6.length >= j + arrayOfByte3.length) {
								System.arraycopy(arrayOfByte6, j, arrayOfByte3, 0, arrayOfByte3.length);
								rearrangeSectorBank(localSectorBank);
							} else {
								arrayOfByte3 = null;
							}
						} catch (NullPointerException localNullPointerException2) {
							Debug.out.println(localNullPointerException2);
							arrayOfByte3 = null;
						} catch (BufferUnderflowException localBufferUnderflowException) {
							arrayOfByte3 = null;
							Debug.out.println(localBufferUnderflowException);
						}
					} else {
						arrayOfByte3 = null;
					}
				}
				if ((arrayOfByte2 != null) && (arrayOfByte3 != null)) {
					System.arraycopy(arrayOfByte2, 0, arrayOfByte1, 0, arrayOfByte2.length);
					System.arraycopy(arrayOfByte3, 0, arrayOfByte1, arrayOfByte2.length, arrayOfByte3.length);
				} else {
					l1 = getSectorKey(this.startingSector);
					if (l1 >= 0L) {
						byte[] arrayOfByte4 = null;
						try {
							localSectorBank = getSectorBank(l1);
							arrayOfByte4 = localSectorBank.getSectorData();
						} catch (NullPointerException localNullPointerException1) {
							arrayOfByte4 = null;
							Debug.out.println(localNullPointerException1);
						}

						if (arrayOfByte4 != null) {
							if (arrayOfByte4.length >= j + i) {
								try {
									System.arraycopy(arrayOfByte4, j, arrayOfByte1, 0, i);
									rearrangeSectorBank(localSectorBank);
								} catch (ArrayIndexOutOfBoundsException localArrayIndexOutOfBoundsException) {
									Debug.out.println(localArrayIndexOutOfBoundsException);
									arrayOfByte1 = null;
								} catch (Exception localException) {
									Debug.out.println(localException);
									arrayOfByte1 = null;
								}

							} else {
								arrayOfByte1 = null;
							}
						} else {
							arrayOfByte1 = null;
						}
					}
				}
			} else {
				arrayOfByte1 = null;
			}
		if (arrayOfByte1 == null) {

			try {
				getRequestHandler().setMissingBankInfo(this.startingSector / 64L * 64L);
				getRequestHandler().setSectorMiss(true);
				arrayOfByte1 = new byte[i];
				arrayOfByte1 = readFromFile(this.startingSector, this.numSectors);
			} catch (IOException localIOException) {
				arrayOfByte1 = null;
				Debug.out.println(localIOException);
			}
			synchronized (getReqSync()) {
				getReqSync().notifyAll();
			}
		}
		return arrayOfByte1;
	}

	public byte[] getSectorData() {
		return this.sectorData;
	}

	private long getSectorKey(long paramLong) {
		long l = paramLong / 64L * 64L;
		if (getSectorBank(l) == null) {
			l = -1L;
		}
		return l;
	}

	public boolean addToCache(byte[] paramArrayOfByte, long paramLong) {
		boolean bool = false;
		if ((getSectorDataCache().size() <= 256) && (getSectorBank(paramLong) == null)) {
			SectorBank localSectorBank = new SectorBank();
			localSectorBank.setSectorKey(paramLong);
			localSectorBank.setSectorData(paramArrayOfByte);
			getSectorDataCache().addFirst(localSectorBank);
			bool = true;
		}

		return bool;
	}

	public SectorBank getSectorBank(long paramLong) {
		Object localObject = null;
		try {
			for (int i = 0; i < getSectorDataCache().size(); i++) {
				SectorBank localSectorBank = (SectorBank) getSectorDataCache().get(i);
				if (localSectorBank.getSectorKey() == paramLong) {
					localObject = localSectorBank;
					break;
				}
			}
		} catch (Exception localException) {
			Debug.out.println(localException);
			localObject = null;
		}
		return (SectorBank) localObject;
	}

	public void rearrangeSectorBank(SectorBank paramSectorBank) {
		if (paramSectorBank != null) {
			int i = getSectorDataCache().indexOf(paramSectorBank);
			if ((i >= 0) && (i < getSectorDataCache().size())) {
				try {
					SectorBank localSectorBank = (SectorBank) getSectorDataCache().remove(i);
					getSectorDataCache().addFirst(localSectorBank);
				} catch (Exception localException) {
					Debug.out.println(localException);
				}
			}
		}
	}

	public byte[] readFromFile(long paramLong, int paramInt) throws IOException {
		byte[] arrayOfByte = new byte[2048 * paramInt];
		if (this.imageFile != null) {

			this.fileReadWait = true;
			synchronized (this.fileLock) {
				if (this.isoReader == null)
					this.isoReader = new ISOReader();
				arrayOfByte = this.isoReader.readSectorData(this.imageFile, paramLong, paramInt);

				this.fileReadWait = false;
				this.fileLock.notifyAll();
			}
		}
		return arrayOfByte;
	}

	public LinkedList<SectorBank> getSectorDataCache() {
		return this.sectorDataCache;
	}

	public void setSectorDataCache(LinkedList<SectorBank> paramLinkedList) {
		this.sectorDataCache = paramLinkedList;
	}

	public RequestHandler getRequestHandler() {
		return this.requestHandler;
	}

	public CacheManager getCacheManager() {
		return this.cacheManager;
	}

	public void startThread() {
		this.running = true;
		start();
	}

	public void stopThread() {
		this.running = false;
	}

	public Object getCacheSync() {
		return this.cacheSync;
	}

	public Object getReadSync() {
		return this.readSync;
	}

	public void setSectorRequest(long paramLong, int paramInt) {
		this.startingSector = paramLong;
		this.numSectors = paramInt;
	}

	public boolean isCacheLocked() {
		return this.cacheLocked;
	}

	public void setCacheLocked(boolean paramBoolean) {
		this.cacheLocked = paramBoolean;
	}

	public Object getCacheLock() {
		return this.cacheLock;
	}

	public Object getFileLock() {
		return this.fileLock;
	}

	public boolean isFileReadWait() {
		return this.fileReadWait;
	}

	public Object getReqSync() {
		return this.reqSync;
	}
}

/*
 * Location:
 * D:\Users\tianlin\Downloads\JViewer.jar!\com\ami\kvm\isocaching\ReadAheadCache
 * .class Java compiler version: 5 (49.0) JD-Core Version: 0.7.1
 */